package com.example.easycharge.notRepEntity;

import com.example.easycharge.entity.MessageItem;
import com.example.easycharge.repository.MessageItemRepository;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;

public class WaitArea {

    private final LinkedList<ChargeRequest> fastArea = new LinkedList<>();
    private final LinkedList<ChargeRequest> slowArea = new LinkedList<>();
    private final HashSet<Long> vehicleIdSet = new HashSet<>();
    private int MAX_AREA_SIZE = 10;
    private int areaSize;
    // 经度范围
    private double longitudeMax=180;
    private double longitudeMIN=0;
    // 纬度范围
    private double latitudeMAX=180;
    private double latitudeMIN=0;

    private static final WaitArea instance = new WaitArea();

    public static WaitArea getInstance() {
        return instance;
    }

    @Autowired
    private MessageItemRepository messageItemRepository;

    public void addNewRequestToArea(ChargeRequest chargeRequest) {
        areaSize++;
        vehicleIdSet.add(chargeRequest.getVehicleId());
        if (chargeRequest.isFastCharge()) {
            fastArea.add(chargeRequest);
        } else {
            slowArea.add(chargeRequest);
        }
    }

    public ChargeRequest getNextRequest(boolean isFast) {
        if (isFast) {
            if (fastArea.size() != 0) {
                areaSize--;
                vehicleIdSet.remove(fastArea.peekFirst().getVehicleId());
                return fastArea.pollFirst();
            }
            return null;
        }
        if (slowArea.size() != 0) {
            areaSize--;
            vehicleIdSet.remove(slowArea.peekFirst().getVehicleId());
            return slowArea.pollFirst();
        }
        return null;
    }

    // 从等待队列中被挤出来的车辆，应该插到等候区的首位上
    public void insertRequest(ChargeRequest chargeRequest) {
        areaSize++;
        vehicleIdSet.add(chargeRequest.getVehicleId());
        if (chargeRequest.isFastCharge()) {
            fastArea.addFirst(chargeRequest);
        } else {
            slowArea.addFirst(chargeRequest);
        }
        // 如果插入车辆后让等候区超了，得移除一个末尾的车辆
        if (areaSize > MAX_AREA_SIZE) {
            if (fastArea.size() < 2) {
                slowArea.pollLast();
                return;
            }
            if (slowArea.size() < 2) {
                fastArea.pollLast();
                return;
            }
            // 其他情况下挑个最迟的踢出去
            ChargeRequest fastCharge = fastArea.peekLast();
            ChargeRequest slowCharge = slowArea.peekLast();
            if (fastCharge.getOrderNumber() > slowCharge.getOrderNumber()) {
                fastArea.pollLast();
            } else {
                slowArea.pollLast();
            }
        }
    }

    public int countAhead(long vehicleId) {
        int aheadCount = 0;

        for (ChargeRequest chargeRequest : fastArea) {
            if (chargeRequest.getVehicleId() == vehicleId) {
                break;
            }
            aheadCount++;
        }
        if (aheadCount != 0) {
            return aheadCount;
        }
        for (ChargeRequest chargeRequest : slowArea) {
            if (chargeRequest.getVehicleId() == vehicleId) {
                break;
            }
            aheadCount++;
        }
        return aheadCount;
    }

    public ChargeRequest getRequestByVehicleId(long vehicleId) {
        for (ChargeRequest chargeRequest : fastArea) {
            if (chargeRequest.getVehicleId() == vehicleId) {
                return chargeRequest;
            }
        }
        for (ChargeRequest chargeRequest : slowArea) {
            if (chargeRequest.getVehicleId() == vehicleId) {
                return chargeRequest;
            }
        }
        return null;
    }

    public void moveToTail(long vehicleId, boolean isFast) {
        // 等候区中的车辆没有预计等待时间的概念
        ChargeRequest removedRequest = null;
        if (isFast) {
            for (ChargeRequest chargeRequest : fastArea) {
                if (chargeRequest.getVehicleId() == vehicleId) {
                    removedRequest = chargeRequest;
                    fastArea.remove(chargeRequest);
                    break;
                }
            }
        } else {
            for (ChargeRequest chargeRequest : slowArea) {
                if (chargeRequest.getVehicleId() == vehicleId) {
                    removedRequest = chargeRequest;
                    slowArea.remove(chargeRequest);
                    break;
                }
            }
        }
        if (removedRequest != null) {
            addNewRequestToArea(removedRequest);
        }
    }

    public void removeTail(int maxSize) {
        if (areaSize <= maxSize) {
            return;
        }
        areaSize = maxSize;
        LinkedList<ChargeRequest> totalRequest = new LinkedList<>(fastArea);
        totalRequest.addAll(slowArea);
        fastArea.clear();
        vehicleIdSet.clear();
        slowArea.clear();
        totalRequest.sort(Comparator.comparingInt(ChargeRequest::getOrderNumber));
        for (int index = 0; index < maxSize; index++) {
            ChargeRequest topRequest = totalRequest.pollFirst();
            vehicleIdSet.add(topRequest.getVehicleId());
            if ((topRequest.isFastCharge())) {
                fastArea.add(topRequest);
            } else {
                slowArea.add(topRequest);
            }
        }
        while (!totalRequest.isEmpty()) {
            ChargeRequest removedRequest = totalRequest.pollFirst();
            // 发送消息即可
            MessageItem messageItem = new MessageItem(removedRequest.getCustomerId(), "因等候区容量调整，您的车辆已被移除等候区，请稍后重新申请1");
            messageItemRepository.saveAndFlush(messageItem);
        }
    }

    public boolean existVehicle(long vehicleId) {
        return vehicleIdSet.contains(vehicleId);
    }

    public boolean cancelCharge(long vehicleId) {
        for (ChargeRequest chargeRequest : fastArea) {
            if (chargeRequest.getVehicleId() == vehicleId) {
                fastArea.remove(chargeRequest);
                vehicleIdSet.remove(chargeRequest.getVehicleId());
                areaSize--;
                return true;
            }
        }
        for (ChargeRequest chargeRequest : slowArea) {
            if (chargeRequest.getVehicleId() == vehicleId) {
                slowArea.remove(chargeRequest);
                vehicleIdSet.remove(chargeRequest.getVehicleId());
                areaSize--;
                return true;
            }
        }
        return false;
    }

    public boolean inArea(ChargeRequest chargeRequest) {
        double longitude = chargeRequest.getLongitude();
        double latitude = chargeRequest.getLatitude();
        if (longitude > longitudeMax || longitude < longitudeMIN) {
            return false;
        }
        return !(latitude > latitudeMAX) && !(latitude < latitudeMIN);
    }

    public int getAreaSize() {
        return areaSize;
    }

    public int fastSize() {
        return fastArea.size();
    }

    public int slowSize() {
        return slowArea.size();
    }

    public void setMAX_AREA_SIZE(int MAX_AREA_SIZE) {
        this.MAX_AREA_SIZE = MAX_AREA_SIZE;
    }

    public double getLongitudeMax() {
        return longitudeMax;
    }

    public double getLongitudeMIN() {
        return longitudeMIN;
    }

    public double getLatitudeMAX() {
        return latitudeMAX;
    }

    public double getLatitudeMIN() {
        return latitudeMIN;
    }

    public void setLongitudeMax(double longitudeMax) {
        this.longitudeMax = longitudeMax;
    }

    public void setLongitudeMIN(double longitudeMIN) {
        this.longitudeMIN = longitudeMIN;
    }

    public void setLatitudeMAX(double latitudeMAX) {
        this.latitudeMAX = latitudeMAX;
    }

    public void setLatitudeMIN(double latitudeMIN) {
        this.latitudeMIN = latitudeMIN;
    }
}
